package com.xinsoft.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.SysNoticeDTO;
import com.xinsoft.entity.dto.SysNoticePageParam;
import com.xinsoft.entity.dto.SysNoticeSetDTO;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.SysNoticeUserVo;
import com.xinsoft.entity.vo.SysNoticeVo;
import com.xinsoft.mapper.SysNoticeMapper;
import com.xinsoft.service.*;
import com.xinsoft.utils.SpringUtils;
import com.xinsoft.utils.TokenUtil;
import com.xinsoft.websocket.WebSocketSessionHolderManager;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* @author xuhb
* @description 针对表【sys_notice(通知表)】的数据库操作Service实现
* @createDate 2023-04-10 11:34:27
*/
@Service
@Slf4j
public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice>
    implements SysNoticeService{

    @Resource
    private SysNoticeSetService sysNoticeSetService;

    @Resource
    private SysActionService actionService;

    @Resource
    private SysNoticeReceiveService sysNoticeReceiveService;

    @Resource
    private SysUserService sysUserService;

    private static WebSocketSessionHolderManager sessionHolderManager = SpringUtils.getBean(WebSocketSessionHolderManager.class);

    @Override
    @Synchronized
    @Transactional(readOnly = false,rollbackFor = Exception.class)
    public void sendNoticeByActionId(List<String> paramValues,@NotNull Integer actionId) {

        List<SysNoticeSetDTO> sysNoticeSetDTOList = sysNoticeSetService.getSysNoticeSetByActionId(actionId);
        if(CollectionUtil.isNotEmpty(sysNoticeSetDTOList)){
            for (SysNoticeSetDTO sysNoticeSetDTO : sysNoticeSetDTOList) {

                List<Integer> receiveIds = new ArrayList<>();
                List<Integer> deptIds = new ArrayList<>();
                List<SysNoticeUserVo> sysNoticeUserList = sysNoticeSetDTO.getSysNoticeUserList();
                if(CollectionUtil.isNotEmpty(sysNoticeUserList)){
                    for (SysNoticeUser sysNoticeUser : sysNoticeUserList) {
                        if(Objects.equals(sysNoticeUser.getDepOrUser(), Const.NOTICE_DEPT)){
                            deptIds.add(sysNoticeUser.getDepId());
                        }
                        if(Objects.equals(sysNoticeUser.getDepOrUser(), Const.NOTICE_USER)){
                            receiveIds.add(sysNoticeUser.getUserId());
                        }
                    }
                }
                //保存接收人
                if(CollectionUtil.isNotEmpty(deptIds)){
                    QueryWrapper userQuery = new QueryWrapper();
                    userQuery.in("dept_id",deptIds);
                    List<SysUser> userList =sysUserService.list(userQuery);
                    if(CollectionUtil.isNotEmpty(userList)){
                        for (SysUser sysUser : userList) {
                            receiveIds.add(sysUser.getId());
                        }
                    }
                }

                // 保存通知消息
                SysNoticeDTO notice = new SysNoticeDTO();
                SysAction sysAction = actionService.getById(actionId);
                notice.setContent(sysNoticeSetDTO.getNoticeContext());
                if(StrUtil.isNotBlank(sysAction.getActionName())){
                    notice.setTitle(sysAction.getActionName());
                }else{
                    notice.setTitle("未配置消息标题");
                }
                // 拼接url
                String urlParam = "";
                if(CollectionUtil.isNotEmpty(paramValues) && StringUtils.isNotEmpty(sysNoticeSetDTO.getHrefParam())){
                    String[] paramKeys = sysNoticeSetDTO.getHrefParam().split(",");
                    if(paramValues.size()== paramKeys.length){
                        // url参数。
                        urlParam = "?"+paramKeys[0]+"="+paramValues.get(0);
                        for (int i = 1; i < paramKeys.length; i++) {
                            urlParam = urlParam+"&"+paramKeys[i]+"="+paramValues.get(i);
                        }
                    }
                }
                notice.setContentUrlParam(sysNoticeSetDTO.getHrefUrl()+urlParam);
                notice.setReceiveIds(receiveIds);
                // 发送
                send(notice);
            }
        }
    }


    @Override
    @Synchronized
    public void send(SysNoticeDTO sysNoticeDTO){

        if (sysNoticeDTO!=null && CollectionUtil.isNotEmpty(sysNoticeDTO.getReceiveIds())){
            //  保存消息
            SysNotice notice = new SysNotice();
            BeanUtils.copyProperties(sysNoticeDTO,notice);
            if (Objects.isNull(notice.getFromUserId())) {
                notice.setFromUserId(TokenUtil.getUserId());
            }
            save(notice);

            // 保存通知人
            SysNoticeReceive receive;
            List<SysNoticeReceive> receiveList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(sysNoticeDTO.getReceiveIds())){
                for (Integer receiverId : sysNoticeDTO.getReceiveIds()) {
                    receive = new SysNoticeReceive();
                    receive.setNoticeId(notice.getId());
                    receive.setSignStatus(0);
                    receive.setUserId(receiverId);
                    receiveList.add(receive);
                }
            }
            // 保存通知人
            sysNoticeReceiveService.saveBatch(receiveList);
            // 发送web通知
            if (CollectionUtil.isNotEmpty(sysNoticeDTO.getReceiveIds())){
                for (Integer receiverId : sysNoticeDTO.getReceiveIds()) {
                    try{
                        sessionHolderManager.sendMessage(String.valueOf(receiverId), JSONObject.toJSONString(notice));
                    }catch(Exception e){
                        log.info(e.getMessage());
                    }
                }
            }
        }
    }

    @Override
    @Synchronized
    public void del(List<Integer> noticeReceiveRelIds){
        sysNoticeReceiveService.removeByIds(noticeReceiveRelIds);
    }

    //阅读
    @Override
    public void read(List<Integer> noticeReceiveRelIds){
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.in("id",noticeReceiveRelIds);
        updateWrapper.set("sign_status",1);
        sysNoticeReceiveService.update(updateWrapper);
    }

    @Override
    public IPage<SysNoticeVo> findPageListByParam(SysNoticePageParam param) {
        //分页
        Page<SysNoticeVo> page = new Page<SysNoticeVo>(param.getCurrentPage(), param.getPageSize());
        QueryWrapper<SysNoticeVo> queryWrapper = new QueryWrapper<>();
        //查询条件
        queryWrapper
                .like(StringUtils.isNotEmpty(param.getFromUserName()),"fromUserName",param.getFromUserName())
                .like(StringUtils.isNotEmpty(param.getTitle()),"title",param.getTitle())
                .eq("receiveId",TokenUtil.getUserId())// 接收人id
                .eq(param.getSignStatus()!=null,"status",param.getSignStatus())
                .eq("do_delete",0)
                .orderByAsc("status")
                .orderByDesc("create_time");
        if (param.getStartTime()!=null){
            queryWrapper.ge("create_time", param.getStartTime());
        }
        if (param.getEndTime()!=null){
            queryWrapper.le("create_time", param.getEndTime());
        }

        IPage<SysNoticeVo> applicationPageList = this.baseMapper.selectPageInfo(page, queryWrapper);

        //返回值
        return applicationPageList;
    }

    @Override
    public int unreadCount() {

        QueryWrapper<SysNoticeVo> queryWrapper = new QueryWrapper<>();
        //查询条件
        queryWrapper
                .eq("receiveId",TokenUtil.getUserId())// 接收人id
                .eq("status",0)
                .eq("do_delete",0);

        int unreadCount = this.baseMapper.unreadCount(queryWrapper);

        //返回值
        return unreadCount;
    }


}




